package com.yangtu.nearbyshop.wx.web;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.mysql.jdbc.StringUtils;
import com.yangtu.nearbyshop.core.corg.until.BeanTools;
import com.yangtu.nearbyshop.core.system.SystemConfig;
import com.yangtu.nearbyshop.core.util.ResponseUtil;
import com.yangtu.nearbyshop.db.domain.*;
import com.yangtu.nearbyshop.db.service.*;
import com.yangtu.nearbyshop.db.service.itf.INearbyshopSettingService;
import com.yangtu.nearbyshop.wx.service.HomeCacheManager;
import com.yangtu.nearbyshop.wx.annotation.LoginUser;
import com.yangtu.nearbyshop.wx.util.JsonUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.constraints.NotNull;
import java.util.*;
import java.util.concurrent.*;

/**
 * 首页服务
 */
@RestController
@RequestMapping("/wx/home")
@Validated
public class WxHomeController {
    private final Log logger = LogFactory.getLog(WxHomeController.class);

    @Autowired
    private NearbyshopAdService adService;

    @Autowired
    private NearbyshopGoodsService goodsService;

    @Autowired
    private NearbyshopBrandService brandService;

    @Autowired
    private NearbyshopTopicService topicService;

    @Autowired
    private NearbyshopCategoryService categoryService;

    @Autowired
    private NearbyshopGrouponRulesService grouponRulesService;

    @Autowired
    private NearbyshopCouponService couponService;

    @Autowired
    private NearbyshopGoodsProductService productServiceService;

    @Autowired
    private NearbyshopCartService cartService;

    @Autowired
    private NearbyshopOrderGoodsService orderGoodsService;

    @Autowired
    private NearbyshopOrderService orderService;

    @Autowired
    private NearbyshopUserService userService;

    @Autowired
    private NearbyshopSystemConfigService systemConfigService;

    @Autowired
    private INearbyshopSettingService settingService;


    private final static ArrayBlockingQueue<Runnable> WORK_QUEUE = new ArrayBlockingQueue<>(9);

    private final static RejectedExecutionHandler HANDLER = new ThreadPoolExecutor.CallerRunsPolicy();

    private static ThreadPoolExecutor executorService = new ThreadPoolExecutor(9, 9, 1000, TimeUnit.MILLISECONDS, WORK_QUEUE, HANDLER);

    @GetMapping("/cache")
    public Object cache(@NotNull String key) {
        if (!key.equals("nearbyshop_cache")) {
            return ResponseUtil.fail();
        }

        // 清除缓存
        HomeCacheManager.clearAll();
        return ResponseUtil.ok("缓存已清除");
    }

    /**
     * 首页数据
     * @param userId 当用户已经登录时，非空。为登录状态为null
     * @return 首页数据
     */
    @GetMapping("/index")
    public Object index(@LoginUser Integer userId) {
        //优先从缓存中读取
        if (HomeCacheManager.hasData(HomeCacheManager.INDEX)) {
            return ResponseUtil.ok(HomeCacheManager.getCacheData(HomeCacheManager.INDEX));
        }
        ExecutorService executorService = Executors.newFixedThreadPool(10);

        Map<String, Object> data = new HashMap<>();

        Callable<List> bannerListCallable = () -> adService.queryIndex();

        Callable<List> channelListCallable = () -> categoryService.queryChannel();

        Callable<List> couponListCallable;
        if(userId == null){
            couponListCallable = () -> couponService.queryList(0, 3);
        } else {
            couponListCallable = () -> couponService.queryAvailableList(userId,0, 3);
        }


        Callable<List> newGoodsListCallable = () -> goodsService.queryByNew(0, SystemConfig.getNewLimit());

        Callable<List> hotGoodsListCallable = () -> goodsService.queryByHot(0, SystemConfig.getHotLimit());

        Callable<List> brandListCallable = () -> brandService.queryVO(0, SystemConfig.getBrandLimit());

        Callable<List> topicListCallable = () -> topicService.queryList(0, SystemConfig.getTopicLimit());

        //团购专区
        Callable<List> grouponListCallable = () -> grouponRulesService.queryList(0, 5);

        Callable<List> floorGoodsListCallable = this::getCategoryList;

        FutureTask<List> bannerTask = new FutureTask<>(bannerListCallable);
        FutureTask<List> channelTask = new FutureTask<>(channelListCallable);
        FutureTask<List> couponListTask = new FutureTask<>(couponListCallable);
        FutureTask<List> newGoodsListTask = new FutureTask<>(newGoodsListCallable);
        FutureTask<List> hotGoodsListTask = new FutureTask<>(hotGoodsListCallable);
        FutureTask<List> brandListTask = new FutureTask<>(brandListCallable);
        FutureTask<List> topicListTask = new FutureTask<>(topicListCallable);
        FutureTask<List> grouponListTask = new FutureTask<>(grouponListCallable);
        FutureTask<List> floorGoodsListTask = new FutureTask<>(floorGoodsListCallable);

        executorService.submit(bannerTask);
        executorService.submit(channelTask);
        executorService.submit(couponListTask);
        executorService.submit(newGoodsListTask);
        executorService.submit(hotGoodsListTask);
        executorService.submit(brandListTask);
        executorService.submit(topicListTask);
        executorService.submit(grouponListTask);
        executorService.submit(floorGoodsListTask);

        try {
            data.put("banner", bannerTask.get());
            data.put("channel", channelTask.get());
            data.put("couponList", couponListTask.get());
            data.put("newGoodsList", newGoodsListTask.get());
            data.put("hotGoodsList", hotGoodsListTask.get());
            data.put("brandList", brandListTask.get());
            data.put("topicList", topicListTask.get());
            data.put("grouponList", grouponListTask.get());
            data.put("floorGoodsList", floorGoodsListTask.get());
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        //缓存数据
        HomeCacheManager.loadData(HomeCacheManager.INDEX, data);
        executorService.shutdown();
        return ResponseUtil.ok(data);
    }

    private List<Map> getCategoryList() {
        List<Map> categoryList = new ArrayList<>();
        List<NearbyshopCategory> catL1List = categoryService.queryL1WithoutRecommend(0, SystemConfig.getCatlogListLimit());
        for (NearbyshopCategory catL1 : catL1List) {
            List<NearbyshopCategory> catL2List = categoryService.queryByPid(catL1.getId());
            List<Integer> l2List = new ArrayList<>();
            for (NearbyshopCategory catL2 : catL2List) {
                l2List.add(catL2.getId());
            }

            List<NearbyshopGoods> categoryGoods;
            if (l2List.size() == 0) {
                categoryGoods = new ArrayList<>();
            } else {
                categoryGoods = goodsService.queryByCategory(l2List, 0, SystemConfig.getCatlogMoreLimit());
            }

            Map<String, Object> catGoods = new HashMap<>();
            catGoods.put("id", catL1.getId());
            catGoods.put("name", catL1.getName());
            catGoods.put("goodsList", categoryGoods);
            categoryList.add(catGoods);
        }
        return categoryList;
    }

    /**
     * 首页数据
     * @param userId 当用户已经登录时，非空。为登录状态为null
     * @return 首页数据
     */
    @GetMapping("/indexNew")
    public Object indexNew(@LoginUser Integer userId) {

        ExecutorService executorService = Executors.newFixedThreadPool(10);

        Map<String, Object> data = new HashMap<>();

        Callable<List> newGoodsListCallable = () -> goodsService.queryByNew(0, SystemConfig.getNewLimit());

        //Callable<List> hotGoodsListCallable = () -> goodsService.queryByHot(0, SystemConfig.getHotLimit());
        Callable<List> hotGoodsListCallable = () -> goodsService.queryByPush(0, SystemConfig.getHotLimit());

        Callable<List> bannerListCallable = () -> adService.queryIndex();

        FutureTask<List> newGoodsListTask = new FutureTask<>(newGoodsListCallable);
        FutureTask<List> hotGoodsListTask = new FutureTask<>(hotGoodsListCallable);
        FutureTask<List> bannerTask = new FutureTask<>(bannerListCallable);

        executorService.submit(newGoodsListTask);
        executorService.submit(hotGoodsListTask);
        executorService.submit(bannerTask);

        try {
            List<NearbyshopGoods> goodsList = newGoodsListTask.get();
            data.put("newGoodsList", getGoodsInfoList(goodsList, userId));
            goodsList = hotGoodsListTask.get();
            data.put("hotGoodsList", getGoodsInfoList(goodsList, userId));
            data.put("banner", bannerTask.get());

        }
        catch (Exception e) {
            e.printStackTrace();
        }
        //缓存数据
        HomeCacheManager.loadData(HomeCacheManager.INDEX, data);
        executorService.shutdown();
        return ResponseUtil.ok(data);
    }

    /**
     * 首页按照商品种类展示商品
     * @param userId 当用户已经登录时，非空。为登录状态为null
     * @return 首页数据
     */
    @GetMapping("/selectCategory")
    public Object selectCategory(@LoginUser Integer userId, @NotNull Integer categoryId) {

        ExecutorService executorService = Executors.newFixedThreadPool(10);

        Map<String, Object> data = new HashMap<>();

        NearbyshopCategory currentCategory = categoryService.findById(categoryId);
        List<NearbyshopCategory> currentSubCategory = categoryService.queryByPid(currentCategory.getId());

        List<Integer> catList = new ArrayList<>();
        for (NearbyshopCategory category:currentSubCategory) {
            catList.add(category.getId());
        }

        Callable<List> goodsListCallable = () -> goodsService.queryByCategory(catList, 0, SystemConfig.getHotLimit());

        FutureTask<List> goodsListTask = new FutureTask<>(goodsListCallable);

        executorService.submit(goodsListTask);

        try {
            List<NearbyshopGoods> goodsList = goodsListTask.get();
            data.put("data", getGoodsInfoList(goodsList, userId));
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        //缓存数据
//        HomeCacheManager.loadData(HomeCacheManager.INDEX, data);
        executorService.shutdown();
        return ResponseUtil.ok(data);
    }

    private List getGoodsInfoList(List<NearbyshopGoods> goodsList, Integer userId){
        List<Map<String, Object>> goodsInfoList = new ArrayList<>();
        Map<String, Object> goosInfoVo;
        for (NearbyshopGoods nearbyshopGoods: goodsList) {
            goosInfoVo = BeanTools.beanToMap(nearbyshopGoods);
            //只能单规格
            goosInfoVo.put("productId", productServiceService.queryByGid(nearbyshopGoods.getId()).get(0).getId());
            Integer limitNum =  productServiceService.queryByGid(nearbyshopGoods.getId()).get(0).getNumber();
            Integer saleNum = limitNum - productServiceService.queryByGid(nearbyshopGoods.getId()).get(0).getNumber();
            goosInfoVo.put("limitNum",limitNum);
            goosInfoVo.put("saleNum", saleNum);
            goosInfoVo.put("startsaleNumber", productServiceService.queryByGid(nearbyshopGoods.getId()).get(0).getStartsaleNumber());
            if (userId == null) {
                goosInfoVo.put("cartNum", 0);
            }else {
                List<NearbyshopCart> cartList = cartService.queryByUidGoodIdCount(userId, nearbyshopGoods.getId());
                int sumNum = 0;
                for (NearbyshopCart cart:cartList) {
                    sumNum += cart.getNumber();
                }
                goosInfoVo.put("cartNum", sumNum);
            }

            List<Map<String, Object>> saleInfoList = new ArrayList<>();
            Map<String, Object> salePeopleInfo;
            List<NearbyshopOrderGoods> orderGoodsList= orderGoodsService.queryByGid(nearbyshopGoods.getId(), 1, 5, "add_time", "desc");
            for (NearbyshopOrderGoods orderGoods:orderGoodsList) {
                salePeopleInfo = new HashMap<>();
                NearbyshopUser user = userService.findById(orderService.findById(orderGoods.getOrderId()).getUserId());
                if(user != null){
                    String nickName ="";
                    if (!StringUtils.isNullOrEmpty(user.getNickname())) {
                        nickName = new String(Base64.getDecoder().decode(user.getNickname()));
                    }
                    salePeopleInfo.put("nickNm", nickName);
                    salePeopleInfo.put("avatarUrl", user.getAvatar());
                    salePeopleInfo.put("saleTm", orderGoods.getAddTime());
                    saleInfoList.add(salePeopleInfo);
                }
            }

            goosInfoVo.put("saleInfo",saleInfoList);

            goodsInfoList.add(goosInfoVo);
        }

        return goodsInfoList;
    }

    /**
     * 商品用户购买数据
     * @param goodsId 商品ID
     * @return 首页数据
     */
    @GetMapping("/saleUserGet")
    public Object getSaleUser(@NotNull Integer goodsId) {

        Map<String, Object> data = new HashMap<>();
        List<Map<String, Object>> saleInfoList = new ArrayList<>();
        Map<String, Object> salePeopleInfo;
        List<NearbyshopOrderGoods> orderGoodsList= orderGoodsService.queryByGid(goodsId, 1, 5, "add_time", "desc");
        for (NearbyshopOrderGoods orderGoods:orderGoodsList) {
            salePeopleInfo = new HashMap<>();
            NearbyshopUser user = userService.findById(orderService.findById(orderGoods.getOrderId()).getUserId());
            String nickName ="";
            if (!StringUtils.isNullOrEmpty(user.getNickname())) {
                nickName = new String(Base64.getDecoder().decode(user.getNickname()));
            }
            salePeopleInfo.put("nickNm", nickName);
            salePeopleInfo.put("avatarUrl", user.getAvatar());
            salePeopleInfo.put("saleTm", orderGoods.getAddTime());
            saleInfoList.add(salePeopleInfo);
        }
        return ResponseUtil.ok(data);
    }

    /**
     * 获取打烊状态接口
     * @return 打烊状态
     */
    @GetMapping("/getOpenStatus")
    public Object getOpenStatus() {
        Map<String, Object> data = new HashMap<>();
        Map<String, String> result = systemConfigService.listWx();
        if(null != result.get("nearbyshop_wx_open_status")){
            data.put("openStatus",(String)result.get("nearbyshop_wx_open_status"));
        }else {
            data.put("openStatus","");
        }
        if(null != result.get("nearbyshop_wx_open_timestr")){
            data.put("openTimestr",(String)result.get("nearbyshop_wx_open_timestr"));
        }else {
            data.put("openTimestr","");
        }
        return ResponseUtil.ok(data);
    }

    /**
     * 获取配置信息
     * @return settingKey
     */
    @GetMapping("/getSetting")
    public Object getSetting(@NotNull String settingKey) {
        NearbyshopSetting setting = settingService.getOne(new QueryWrapper<NearbyshopSetting>()
                .eq("setting_key",settingKey));
        if(null == setting){
            if("mercGuide".equals(settingKey)){
                setting = new NearbyshopSetting();
                setting.setSettingKey("mercGuide");
                setting.setSettingValue("暂无规则");
            }else if("creditUrl".equals(settingKey)){
                setting = new NearbyshopSetting();
                setting.setSettingKey("creditUrl");

                List<Map<String,String>> map = new ArrayList<>();
                Map<String,String> m1 = new HashMap<>();
                m1.put("img","111");
                m1.put("url","https://wm.cib.com.cn/html/webapp/fast-issue/home.html?id=26da39a38ab94e2f983f6336196f63ba");
                map.add(m1);
                Map<String,String> m2 = new HashMap<>();
                m2.put("img","222");
                m2.put("url","https://creditcard.cmbc.com.cn/wsv2/?enstr=eCsL0rn%2b2z0tCH%2bz5gpynrvWBMIL0pw0WS73MfFs2GwVMGSleZfsU5XIsOBpYkfUlsQpeDBrjaxfDqOemvviWlBMLPpqS8slTM%2b0ly4c%2fnLWJzH6k63LkKgl5bKPzUVaZCKFDszLXZYYHtuPfyDyrI64NHVqaPbLO%2bUrhGRjj8%2b61bigK4XHsd3zzl6jmrNW0Gs3HvgFh9q6LgXOWfLpi4PIv59kp9LoDQhPlTsxzvcWnrhQZ5Oh%2beLjKGaTU5rBCRONhfjpWTweXY9HRbOjbgdGgeQ7vFO2qn72xaFbzTVlNS%2ftll9RU6sC8rNomfso0kzr1XHGzir05IkRUc72pA%3d%3d");
                map.add(m2);
                setting.setSettingValue(JsonUtils.bean2Json(map));
            }
            settingService.save(setting);
        }
        return ResponseUtil.ok(setting);
    }


}
